<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 7.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.ico">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha256-wiz7ZSCn/btzhjKDQBms9Hx4sSeUYsDrTLg7roPstac=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.css" integrity="sha256-6cQIC71/iBIYXFK+0RHAvwmjwWzkWd+r7v/BX3/vZDc=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/themes/green/pace-theme-minimal.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/pace.min.js" integrity="sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0=" crossorigin="anonymous"></script>

<script class="next-config" data-name="main" type="application/json">{"hostname":"sumumm.github.io","root":"/","images":"/images","scheme":"Gemini","darkmode":false,"version":"8.19.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"mac"},"fold":{"enable":true,"height":300},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":true,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="本文主要是进程通信——信号量的相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。">
<meta property="og:type" content="article">
<meta property="og:title" content="LV05-05-进程通信-06-信号量">
<meta property="og:url" content="https://sumumm.github.io/post/98ffd47a.html">
<meta property="og:site_name" content="苏木">
<meta property="og:description" content="本文主要是进程通信——信号量的相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV05-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/LV05-05-%E8%BF%9B%E7%A8%8B%E9%80%9A%E4%BF%A1-06-%E4%BF%A1%E5%8F%B7%E9%87%8F/img/1.gif">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV05-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/LV05-05-%E8%BF%9B%E7%A8%8B%E9%80%9A%E4%BF%A1-06-%E4%BF%A1%E5%8F%B7%E9%87%8F/img/2.gif">
<meta property="article:published_time" content="2023-07-02T13:52:27.000Z">
<meta property="article:modified_time" content="2025-06-13T16:25:56.995Z">
<meta property="article:author" content="苏木">
<meta property="article:tag" content="LV05-操作系统">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV05-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/LV05-05-%E8%BF%9B%E7%A8%8B%E9%80%9A%E4%BF%A1-06-%E4%BF%A1%E5%8F%B7%E9%87%8F/img/1.gif">


<link rel="canonical" href="https://sumumm.github.io/post/98ffd47a.html">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://sumumm.github.io/post/98ffd47a.html","path":"post/98ffd47a.html","title":"LV05-05-进程通信-06-信号量"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>LV05-05-进程通信-06-信号量 | 苏木</title>
  








    <script src="/js/browser_tools_disable.js"></script>

  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
<!-- hexo injector head_end start --><link rel="stylesheet" href="https://unpkg.com/hexo-next-tags-plus@latest/lib/tag_plus.css" media="defer" onload="this.media='all'"><!-- hexo injector head_end end --></head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">苏木</p>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">我的学习之路</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>苏木的家</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类页<span class="badge">42</span></a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档页<span class="badge">673</span></a></li><li class="menu-item menu-item-flink"><a href="/flink/" rel="section"><i class="fa fa-link fa-fw"></i>友人帐</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于我</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">一、信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%AE%80%E4%BB%8B"><span class="nav-text">1. 信号量简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%9A%84%E6%93%8D%E4%BD%9C"><span class="nav-text">2. 信号量的操作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-P-%E6%93%8D%E4%BD%9C-%E7%94%B3%E8%AF%B7%E8%B5%84%E6%BA%90"><span class="nav-text">2.1 P 操作(申请资源)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-V-%E6%93%8D%E4%BD%9C-%E9%87%8A%E6%94%BE%E8%B5%84%E6%BA%90"><span class="nav-text">2.2 V 操作(释放资源)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E4%BA%92%E6%96%A5%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">3. 互斥信号量</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E5%90%8C%E6%AD%A5%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">4. 同步信号量</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%A7%8D%E7%B1%BB"><span class="nav-text">5. 信号量种类</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81POSIX-%E6%9C%89%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">二、POSIX 有名信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E5%88%9B%E5%BB%BA%E6%88%96%E6%89%93%E5%BC%80%E6%9C%89%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">1. 创建或打开有名信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-sem-open"><span class="nav-text">1.1 sem_open() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">1.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">1.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E5%85%B3%E9%97%AD%E6%9C%89%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">2. 关闭有名信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-sem-close"><span class="nav-text">2.1 sem_close() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">2.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">2.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E5%88%A0%E9%99%A4%E6%9C%89%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">3. 删除有名信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-sem-unlink"><span class="nav-text">3.1 sem_unlink() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#3-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">3.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">3.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E6%9C%89%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%9A%84P%E6%93%8D%E4%BD%9C"><span class="nav-text">4. 有名信号量的P操作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#4-1-sem-wait"><span class="nav-text">4.1 sem_wait() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#4-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">4.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">4.1.2 使用实例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-2-sem-trywait"><span class="nav-text">4.2 sem_trywait() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#4-2-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">4.2.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-2-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">4.2.2 使用实例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-3-sem-trywait"><span class="nav-text">4.3 sem_trywait()</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#4-3-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">4.3.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-3-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">4.3.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-%E6%9C%89%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%9A%84V%E6%93%8D%E4%BD%9C"><span class="nav-text">5. 有名信号量的V操作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#5-1-sem-post"><span class="nav-text">5.1 sem_post() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#5-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">5.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">5.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">6. 使用实例</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81POSIX-%E6%97%A0%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">三、POSIX 无名信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E5%88%9D%E5%A7%8B%E5%8C%96%E6%97%A0%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">1. 初始化无名信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-sem-init"><span class="nav-text">1.1 sem_init() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E-1"><span class="nav-text">1.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B-1"><span class="nav-text">1.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E9%94%80%E6%AF%81%E6%97%A0%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">2. 销毁无名信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-sem-destroy"><span class="nav-text">2.1 sem_destroy() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E-1"><span class="nav-text">2.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B-1"><span class="nav-text">2.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E6%97%A0%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%9A%84P%E6%93%8D%E4%BD%9C"><span class="nav-text">3. 无名信号量的P操作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-sem-wait"><span class="nav-text">3.1 sem_wait()</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#3-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E-1"><span class="nav-text">3.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B-1"><span class="nav-text">3.1.2 使用实例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-sem-trywait"><span class="nav-text">3.2 sem_trywait() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#3-2-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">3.2.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-2-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">3.2.2 使用实例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-3-sem-trywait"><span class="nav-text">3.3 sem_trywait() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-text">3.3.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">3.3.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E6%97%A0%E5%90%8D%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%9A%84V%E6%93%8D%E4%BD%9C"><span class="nav-text">4. 无名信号量的V操作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#4-1-sem-post"><span class="nav-text">4.1 sem_post() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#4-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E-1"><span class="nav-text">4.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B-1"><span class="nav-text">4.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">5. 使用实例</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81System-V-%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">四、System V 信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E5%88%9B%E5%BB%BA%E6%88%96%E6%89%93%E5%BC%80%E4%BF%A1%E5%8F%B7%E9%87%8F"><span class="nav-text">1. 创建或打开信号量</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-semget"><span class="nav-text">1.1 semget() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E-2"><span class="nav-text">1.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B-2"><span class="nav-text">1.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E4%BF%A1%E5%8F%B7%E9%87%8FP%E3%80%81V%E6%93%8D%E4%BD%9C%E5%AE%9E%E7%8E%B0"><span class="nav-text">2. 信号量P、V操作实现</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-semop"><span class="nav-text">2.1 semop() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E-2"><span class="nav-text">2.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B-2"><span class="nav-text">2.1.2 使用实例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-Poperation"><span class="nav-text">2.2 Poperation() </span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-Voperation"><span class="nav-text">2.3 Voperation() </span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E4%BF%A1%E5%8F%B7%E9%87%8F%E9%9B%86%E6%8E%A7%E5%88%B6"><span class="nav-text">3. 信号量集控制</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-semctl"><span class="nav-text">3.1 semctl() </span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#3-1-1-%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E-2"><span class="nav-text">3.1.1 函数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-1-2-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B-2"><span class="nav-text">3.1.2 使用实例</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">4. 使用实例</span></a></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="苏木"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">苏木</p>
  <div class="site-description" itemprop="description">莫道桑榆晚，为霞尚满天</div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">673</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">42</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">43</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author animated">
      <span class="links-of-author-item">
        <a href="https://github.com/sumumm" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;sumumm" rel="noopener me" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
  </div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://sumumm.github.io/post/98ffd47a.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="苏木">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="苏木">
      <meta itemprop="description" content="莫道桑榆晚，为霞尚满天">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="LV05-05-进程通信-06-信号量 | 苏木">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          LV05-05-进程通信-06-信号量
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2023-07-02 21:52:27" itemprop="dateCreated datePublished" datetime="2023-07-02T21:52:27+08:00">2023-07-02</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/" itemprop="url" rel="index"><span itemprop="name">嵌入式开发</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/" itemprop="url" rel="index"><span itemprop="name">01HQ课程体系</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV05-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" itemprop="url" rel="index"><span itemprop="name">LV05-操作系统</span></a>
        </span>
    </span>

  
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>10k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>37 分钟</span>
    </span>
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody"><p>本文主要是进程通信——信号量的相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。</p>
<span id="more"></span>

<!-- Photo: https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV05-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/LV05-05-%E8%BF%9B%E7%A8%8B%E9%80%9A%E4%BF%A1-06-%E4%BF%A1%E5%8F%B7%E9%87%8F/img/ -->

<details class="folding-tag" blue><summary> 点击查看使用工具及版本 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center" width=150px>Windows</td>        <td align="left">windows11</td>    </tr>    <tr>        <td align="center">Ubuntu</td>        <td align="left">Ubuntu16.04的64位版本</td>      </tr>    <tr>        <td align="center">VMware® Workstation 16 Pro</td>        <td align="left">16.2.3 build-19376536</td>      </tr>    <tr>        <td align="center">SecureCRT</td>        <td align="left">Version 8.7.2 (x64 build 2214)   -   正式版-2020年5月14日</td>      </tr>    <tr>        <td align="center">开发板</td>        <td align="left">正点原子 i.MX6ULL Linux阿尔法开发板</td>      </tr>    <tr>        <td align="center">uboot</td>        <td align="left">NXP官方提供的uboot，NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)</td>      </tr>    <tr>        <td align="center">linux内核</td>        <td align="left">linux-4.15(NXP官方提供)</td>      </tr>    <tr>        <td align="center">STM32开发板</td>        <td align="left">正点原子战舰V3(STM32F103ZET6)</td>      </tr></table>
              </div>
            </details>

<details class="folding-tag" blue><summary> 点击查看本文参考资料 </summary>
              <div class='content'>
              <table>    <tr><td align="center">参考方向  </td><td align="center">参考原文</td></tr>    <tr><td align="left">---</td><td align="left"><a href="" target="_blank">--- <i class="fa fa-external-link-alt"></i> </a></td></tr></table>
              </div>
            </details>

<details class="folding-tag" blue><summary> 点击查看相关文件下载 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center" width=150>---</td>        <td align="left"><a href="" target="_blank">---<i class="fa fa-external-link-alt"></i> </a></td>      </tr></table>
              </div>
            </details>

<h1 id="一、信号量"><a href="#一、信号量" class="headerlink" title="一、信号量"></a><font size=3>一、信号量</font></h1><p>其实前边我们在学习进程通信的时候，会不会有一个疑问，就是多个进程同时写一块区域的时候咋办？或者说那个进程在写，这个来读，读到的数据会不会就有问题呢？进程中没有像线程的互斥锁这些东西来保护共享的资源，但是我们可以使用信号量来达到相同的效果。</p>
<h2 id="1-信号量简介"><a href="#1-信号量简介" class="headerlink" title="1. 信号量简介"></a><font size=3>1. 信号量简介</font></h2><p>信号量是一个计数器，与其它进程间通信方式不大相同，它主要用于<strong>控制多个进程间或一个进程内的多个线程间对共享资源的访问</strong>，相当于内存中的标志，进程可以根据它判定是否能够访问某些共享资源，同时，进程也可以修改该标志，除了用于共享资源的访问控制外，还可用于进程同步。</p>
<p>常被作为一种锁机制，防止某进程在访问资源时其它进程也访问该资源，因此，信号量主要作为进程间以及同一个进程内不同线程之间的同步手段，而不是用于缓存进程间通信的数据。</p>
<h2 id="2-信号量的操作"><a href="#2-信号量的操作" class="headerlink" title="2. 信号量的操作"></a><font size=3>2. 信号量的操作</font></h2><p>信号量代表某一类资源，其值表示系统中该资源的数量，只能通过三种操作来访问它：</p>
<ul>
<li><p>（1）初始化</p>
</li>
<li><p>（2）<code>P</code>操作(申请资源)</p>
</li>
<li><p>（3）<code>V</code>操作(释放资源)</p>
</li>
</ul>
<p>【注意事项】<code>P</code> 操作是用在进入共享资源之前，<code>V</code> 操作是用在离开共享资源之后，这两个操作是<strong>必须成对出现</strong>的。</p>
<h3 id="2-1-P-操作-申请资源"><a href="#2-1-P-操作-申请资源" class="headerlink" title="2.1 P 操作(申请资源)"></a><font size=3>2.1 P 操作(申请资源)</font></h3><p><code>P</code>操作其实就是将信号量减去 <code>1</code>，相减后如果信号量<code>&lt; 0</code>，则表明资源已被占用，没有资源可用，进程需阻塞等待，进入等待队列；相减后如果信号量 <code>&gt;= 0</code>，则表明还有资源可使用，进程可正常继续执行。也就是</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">信号量的值 - <span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span>(信号量的值 ≥ <span class="number">0</span>) </span><br><span class="line">&#123;  </span><br><span class="line"> 	申请资源的任务继续运行;</span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">else</span> </span><br><span class="line">&#123;   </span><br><span class="line">	申请资源的任务阻塞,并插入等待队列;</span><br><span class="line">&#125; </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="2-2-V-操作-释放资源"><a href="#2-2-V-操作-释放资源" class="headerlink" title="2.2 V 操作(释放资源)"></a><font size=3>2.2 V 操作(释放资源)</font></h3><p><code>V</code> 操作会把信号量加上 <code>1</code>，相加后如果信号量 <code>&lt;= 0</code>，则表明当前有阻塞中的进程，于是会从等待队列中取出一个进程唤醒运行；相加后如果信号量 <code>&gt; 0</code>，则表明当前没有阻塞中的进程。也就是</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">信号量的值 + <span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span> (信号量的值 &lt;= <span class="number">0</span>) </span><br><span class="line">&#123;   </span><br><span class="line">	唤醒等待队列的一个任务，让其继续运行;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3-互斥信号量"><a href="#3-互斥信号量" class="headerlink" title="3. 互斥信号量"></a><font size=3>3. 互斥信号量</font></h2><p>上边的已经了解了信号量的操作，那具体是怎样工作的呢？比如我们现在有两个进程：进程<code>1</code>和进程<code>2</code>，还有一个信号量<code>sem</code>，我们将信号量<code>sem</code>初始化为<code>1</code>然后进程<code>1</code>和进程<code>2</code>都要访问共享内存。</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV05-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/LV05-05-%E8%BF%9B%E7%A8%8B%E9%80%9A%E4%BF%A1-06-%E4%BF%A1%E5%8F%B7%E9%87%8F/img/1.gif" alt="2" style="zoom:60%;" />



<p>进程 <code>1</code>在访问共享内存前，先执行了 <code>P</code> 操作，信号量<code>sem</code>的初始值为 <code>1</code>，故在进程 <code>1</code> 执行 <code>P</code> 操作后信号量<code>sem</code>变为 <code>0</code>，表示共享内存可用，于是进程 <code>1</code> 就可以访问共享内存。</p>
<p>进程<code>1</code>正在访问共享内存，进程 <code>2</code> 也想访问共享内存，执行了 <code>P</code> 操作，会使信号量<code>sem</code>变为<code> -1</code>，这就意味着共享内存已被占用，因此进程 <code>2</code> 被阻塞。</p>
<p>当进程 <code>1</code> 访问完共享内存，才会执行 <code>V</code> 操作，使得信号量<code>sem</code>恢复为 <code>0</code>，接着就会唤醒阻塞中的线程 <code>2</code>，使得进程 <code>2</code> 可以访问共享内存，最后完成共享内存的访问后，执行 <code>V</code> 操作，信号量<code>sem</code>恢复到初始值 <code>1</code>。</p>
<p>由此我们知道，信号初始化为 <code>1</code>，就代表着是<strong>互斥信号量</strong>，它可以保证共享内存在任何时刻只有一个进程在访问，这就达到了保护了共享内存的目的。</p>
<h2 id="4-同步信号量"><a href="#4-同步信号量" class="headerlink" title="4. 同步信号量"></a><font size=3>4. 同步信号量</font></h2><p>前边我们在学习线程的时候，有一个生产者与消费者的问题，生产者生产了产品后，消费者才能使用产品，进程之间是否也可以这样呢？我们假设有两个进程，分别为进程<code>1</code>和进程<code>2</code>，进程<code>1</code>负责生产产品，进程<code>2</code>负责使用产品，初始的信号量<code>sem</code>我们初始化为<code>0</code>。</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV05-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/LV05-05-%E8%BF%9B%E7%A8%8B%E9%80%9A%E4%BF%A1-06-%E4%BF%A1%E5%8F%B7%E9%87%8F/img/2.gif" alt="2" style="zoom:60%;" />

<p>如果进程 <code>2</code> 比进程 <code>1</code> 先执行，那么执行到 <code>P</code> 操作时，而信号量<code>sem</code>初始值为 <code>0</code>，所以信号量<code>sem</code>会变为 <code>-1</code>，表示进程 <code>1</code> 还没生产产品，于是进程 <code>2</code> 就阻塞等待；</p>
<p>当进程 <code>1</code> 生产完产品后，执行了 <code>V </code>操作，就会使得信号量<code>sem</code>变为 <code>0</code>，于是就会唤醒阻塞在 <code>P</code> 操作的进程 <code>2</code>；</p>
<p>进程 <code>2</code> 被唤醒后，意味着进程 <code>1</code> 已经生产了数据，于是进程 <code>2</code> 就可以正常使用产品啦了。</p>
<p>由此可知，信号初始化为 <code>0</code>，就代表着是<strong>同步信号量</strong>，这样可以保证进程 <code>1</code> 应在进程 <code>2</code> 之前执行。</p>
<h2 id="5-信号量种类"><a href="#5-信号量种类" class="headerlink" title="5. 信号量种类"></a><font size=3>5. 信号量种类</font></h2><p>一共有三种信号量，分别是<code>POXIX</code>中的无名信号量和有名信号量，以及<code>System V</code>信号量。</p>
<ul>
<li><code>POSIX</code>中的<strong>无名信号量主要用于线程间的通信</strong>，保存在内存中，如果想要在进程间同步就必须把无名信号量放在进程间的共享内存中。</li>
</ul>
<p>而在<strong>进程间的通信中同步用的通常是有名信号量</strong>，有名信号量一般保存在<code>/dev/shm/</code> 目录下，它就像文件一样存储在文件系统中。</p>
<ul>
<li><code>System V</code> 信号量是一个或多个计数信号量的集合，可同时操作集合中的多个信号量，并且申请多个资源时可以避免死锁。</li>
</ul>
<h1 id="二、POSIX-有名信号量"><a href="#二、POSIX-有名信号量" class="headerlink" title="二、POSIX 有名信号量"></a><font size=3>二、POSIX 有名信号量</font></h1><p>这部分是关于有名信号量使用的笔记，需要注意的是有名信号量是随内核持续的，所以如果我们不调用<code>sem_unlink</code>来删除它，它将会一直存在，直到内核重启。另外，该信号量的使用需要借助于共享内存，打开或者创建之前需要进行以下步骤：</p>
<ul>
<li>（1）申请<code>key</code>；</li>
<li>（2）创建共享内存区域；</li>
<li>（3）映射内存区域到进程的虚拟地址空间。</li>
</ul>
<h2 id="1-创建或打开有名信号量"><a href="#1-创建或打开有名信号量" class="headerlink" title="1. 创建或打开有名信号量"></a><font size=3>1. 创建或打开有名信号量</font></h2><h3 id="1-1-sem-open"><a href="#1-1-sem-open" class="headerlink" title="1.1 sem_open() "></a><font size=3>1.1 sem_open() </font></h3><h4 id="1-1-1-函数说明"><a href="#1-1-1-函数说明" class="headerlink" title="1.1.1 函数说明"></a><font size=3>1.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_open</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span>           <span class="comment">/* For O_* constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span>        <span class="comment">/* For mode constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">sem_t</span> *<span class="title function_">sem_open</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *name, <span class="type">int</span> oflag)</span>;</span><br><span class="line"><span class="type">sem_t</span> *<span class="title function_">sem_open</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *name, <span class="type">int</span> oflag, <span class="type">mode_t</span> mode, <span class="type">unsigned</span> <span class="type">int</span> value)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于打开或者创建一个有名信号量。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>name</code>：<code>char *</code>类型，该参数表示信号量的名字（最好不要包含路径，可能会报<code>no such file or diratory</code>）。</li>
</ul>
<details class="folding-tag" blue><summary> 使用 man 7 sem_overview查看该参数详细的说明 </summary>
              <div class='content'>
              <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">A  named  semaphore  is  identified  by a name of the form /somename; that is, a null-terminated string of up to NAME_MAX-4 (i.e., 251) characters consisting of an initial slash, followed by one or more characters, none of which are slashes.  Two processes can operate on the same named semaphore by passing the same name to sem_open(3).</span><br></pre></td></tr></table></figure><p>很明显说明，<code>name</code>参数的构造是以  <code>/</code>号开头，后面跟的字符串不能再有 <code>/</code> 号，长度小于<code>NAME_MAX - 4</code>。所以最好不要在这里指定一个路径，创建的有名信号灯文件默认都保存在<code>/dev/shm</code>路径下，也不需要我们来指定路径。</p>
              </div>
            </details>

<ul>
<li><code>oflag</code>：<code>int</code>类型，选择创建或者打开一个信号量，由于此函数会创建有名信号量文件，所以这里一般可以通过<code>|</code>与表示文件存取权限的宏（如<code>O_RDWR</code>）一起使用。 一般选择<code>O_CREAT|O_RDWR</code>参数，表示以可读写的方式创建并初始化一个信号量，此时<code>mode</code>和<code>value</code>参数是被需要的。如果指定了<code>O_CREAT</code>，并且给定名称的信号量已经存在，那么<code>mode</code>和<code>value</code>将被忽略。</li>
</ul>
<details class="folding-tag" blue><summary> 点击查看 oflag 参数取值 </summary>
              <div class='content'>
              <p>我是查看了<code>man</code>手册，大概就是这两点吧。</p><table>    <tr><td align="center" width=170px>O_CREAT</td><td align="left">如果信号量不存在，就会创建信号量并初始化，函数第三个和第四个参数是必要的的。</td></tr>    <tr><td align="center" width=170px>O_CREAT|O_EXCL</td><td align="left">如果给定名称的信号量已经存在，则返回一个错误。</td></tr></table>
              </div>
            </details>

<ul>
<li><code>mode</code>：<code>mode_t</code>类型，表示文件权限，常用参数为<code>0666</code>。</li>
<li><code>value</code>：<code>unsigned int</code> 类型，表示信号量的初始值。该初始不能超过<code>SEM_VALUE_MAX</code>，这个常值必须低于为<code>32767</code>。二值信号量的初始值通常为<code>1</code>，计数信号量的初始值则往往大于<code>1</code>。</li>
</ul>
<p><strong>【返回值】</strong><code>sem_t *</code>类型，成功返回新信号量的地址，失败返回<code>SEM_FAILED</code>，并设置<code>errno</code>表示错误。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span>           <span class="comment">/* For O_* constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span>        <span class="comment">/* For mode constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line">sem_r = sem_open(<span class="string">&quot;mysem_r&quot;</span>, O_CREAT|O_RDWR, <span class="number">0666</span>, <span class="number">0</span>);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong>创建的信号量文件在<code>/dev/shm</code>目录下。</p>
<h4 id="1-1-2-使用实例"><a href="#1-1-2-使用实例" class="headerlink" title="1.1.2 使用实例"></a><font size=3>1.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="2-关闭有名信号量"><a href="#2-关闭有名信号量" class="headerlink" title="2. 关闭有名信号量"></a><font size=3>2. 关闭有名信号量</font></h2><h3 id="2-1-sem-close"><a href="#2-1-sem-close" class="headerlink" title="2.1 sem_close() "></a><font size=3>2.1 sem_close() </font></h3><h4 id="2-1-1-函数说明"><a href="#2-1-1-函数说明" class="headerlink" title="2.1.1 函数说明"></a><font size=3>2.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_close</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_close</span><span class="params">(<span class="type">sem_t</span> *sem)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于关闭一个信号量。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，需要关闭的信号量的地址。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line">sem_close(sem_r);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="2-1-2-使用实例"><a href="#2-1-2-使用实例" class="headerlink" title="2.1.2 使用实例"></a><font size=3>2.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="3-删除有名信号量"><a href="#3-删除有名信号量" class="headerlink" title="3. 删除有名信号量"></a><font size=3>3. 删除有名信号量</font></h2><h3 id="3-1-sem-unlink"><a href="#3-1-sem-unlink" class="headerlink" title="3.1 sem_unlink() "></a><font size=3>3.1 sem_unlink() </font></h3><h4 id="3-1-1-函数说明"><a href="#3-1-1-函数说明" class="headerlink" title="3.1.1 函数说明"></a><font size=3>3.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_unlink</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_unlink</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *name)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于删除一个有名信号量。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>name</code>：<code>char *</code>类型，表示需要删除的有名信号量的名称，若名称并非使用变量指定，可以直接将名称用<code>&quot; &quot;</code>包裹即可。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line">sem_unlink(<span class="string">&quot;sem_name&quot;</span>);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong>当我们一个进程运行完毕的时候，信号量是一直存在的，当我们下一次重新运行这个进程，由于信号量存在，这就可能会导致出现一些问题，所以我们一般会自定义一个信号处理函数，在信号处理函数中使用该删除函数删除有名信号量。</p>
<h4 id="3-1-2-使用实例"><a href="#3-1-2-使用实例" class="headerlink" title="3.1.2 使用实例"></a><font size=3>3.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="4-有名信号量的P操作"><a href="#4-有名信号量的P操作" class="headerlink" title="4. 有名信号量的P操作"></a><font size=3>4. 有名信号量的<code>P</code>操作</font></h2><p><code>P</code>操作其实就是获取资源，如果信号量为<code>0</code>，表示这时没有相应资源空闲，那么调用进程就将挂起，直到有空闲资源可以获取。</p>
<h3 id="4-1-sem-wait"><a href="#4-1-sem-wait" class="headerlink" title="4.1 sem_wait() "></a><font size=3>4.1 sem_wait() </font></h3><h4 id="4-1-1-函数说明"><a href="#4-1-1-函数说明" class="headerlink" title="4.1.1 函数说明"></a><font size=3>4.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_wait</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_wait</span><span class="params">(<span class="type">sem_t</span> *sem)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于执行信号量的<code>P</code>操作，也就是获取资源。如果信号量的值大于<code>0</code>，则信号量继续递减，函数立即返回；如果信号量当前的值是<code>0</code>，那么调用就会阻塞，直到可以执行递减操作(即信号量的值升到<code>0</code>以上)，或者信号处理程序中断调用。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，表示需要等待的信号量。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line">sem_wait(sem_r);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="4-1-2-使用实例"><a href="#4-1-2-使用实例" class="headerlink" title="4.1.2 使用实例"></a><font size=3>4.1.2 使用实例</font></h4><p>暂无。</p>
<h3 id="4-2-sem-trywait"><a href="#4-2-sem-trywait" class="headerlink" title="4.2 sem_trywait() "></a><font size=3>4.2 sem_trywait() </font></h3><h4 id="4-2-1-函数说明"><a href="#4-2-1-函数说明" class="headerlink" title="4.2.1 函数说明"></a><font size=3>4.2.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_trywait</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_trywait</span><span class="params">(<span class="type">sem_t</span> *sem)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于执行信号量的<code>P</code>操作。<code>sem_trywait()</code>与<code>sem_wait()</code>相同，不同之处是如果不能立即执行递减操作而需要等待的话，调用此函数将返回错误(<code>errno</code>设置为<code>EAGAIN</code>)而不是阻塞。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，表示需要等待的信号量。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line">sem_trywait(sem_r);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="4-2-2-使用实例"><a href="#4-2-2-使用实例" class="headerlink" title="4.2.2 使用实例"></a><font size=3>4.2.2 使用实例</font></h4><p>暂无。</p>
<h3 id="4-3-sem-trywait"><a href="#4-3-sem-trywait" class="headerlink" title="4.3 sem_trywait()"></a><font size=3>4.3 sem_trywait()</font></h3><h4 id="4-3-1-函数说明"><a href="#4-3-1-函数说明" class="headerlink" title="4.3.1 函数说明"></a><font size=3>4.3.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_trywait</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_timedwait</span><span class="params">(<span class="type">sem_t</span> *sem, <span class="type">const</span> <span class="keyword">struct</span> timespec *abs_timeout)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于执行信号量的<code>P</code>操作。<code>sem_timedwait()</code>与<code>sem_wait()</code>相同，不同的是<code>abs_timeout</code>指定了如果不能立即执行递减操作而需要等待的时间，超时将会返回。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，表示需要等待的信号量。</li>
<li><code>abs_timeout</code>：<code>struct timespec</code>类型的结构体指针变量，它指向一个时间结构体，该时间结构体指定了自<code>Epoch (1970-01-01 00:00:00 +0000 (UTC))</code>以来的以秒和纳秒为单位的绝对超时。</li>
</ul>
<details class="folding-tag" blue><summary> 点击查看 struct timespec 结构体成员 </summary>
              <div class='content'>
              <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">timespec</span> </span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">	<span class="type">time_t</span> tv_sec;      <span class="comment">/* Seconds */</span></span><br><span class="line">	<span class="type">long</span>   tv_nsec;     <span class="comment">/* Nanoseconds [0 .. 999999999] */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
              </div>
            </details>

<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">timespec</span> <span class="title">tout</span>;</span></span><br><span class="line">sem_timedwait(sem_r, &amp;tout);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong>如果可以立即执行操作，那么<code>sem_timedwait()</code>永远不会出现超时错误，而不管<code>abs_timeout</code>的值是多少。</p>
<h4 id="4-3-2-使用实例"><a href="#4-3-2-使用实例" class="headerlink" title="4.3.2 使用实例"></a><font size=3>4.3.2 使用实例</font></h4><p>暂无。</p>
<h2 id="5-有名信号量的V操作"><a href="#5-有名信号量的V操作" class="headerlink" title="5. 有名信号量的V操作"></a><font size=3>5. 有名信号量的<code>V</code>操作</font></h2><p><code>V</code>操作就是释放资源，如果没有进程阻塞在该信号量上，表示没有进程等待该资源，这时该函数就对信号量的值进行加<code>1</code>操作，表示同类资源多增加了一个。如果至少有一个进程阻塞在该信号量上，表示有进程等待资源，信号量为<code>0</code>，这时该函数保持信号量为<code>0</code>不变，并使某个阻塞在该信号量上的进程从<code>sem_wait()</code>函数中返回。</p>
<h3 id="5-1-sem-post"><a href="#5-1-sem-post" class="headerlink" title="5.1 sem_post() "></a><font size=3>5.1 sem_post() </font></h3><h4 id="5-1-1-函数说明"><a href="#5-1-1-函数说明" class="headerlink" title="5.1.1 函数说明"></a><font size=3>5.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_post</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_post</span><span class="params">(<span class="type">sem_t</span> *sem)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于执行信号量的<code>V</code>操作，也就是获取资源。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，表示需释放的信号量。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line">sem_post(sem_r);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="5-1-2-使用实例"><a href="#5-1-2-使用实例" class="headerlink" title="5.1.2 使用实例"></a><font size=3>5.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="6-使用实例"><a href="#6-使用实例" class="headerlink" title="6. 使用实例"></a><font size=3>6. 使用实例</font></h2><details class="folding-tag" blue><summary> 点击查看实例 </summary>
              <div class='content'>
              <div class="tabs" id="tabname1"><ul class="nav-tabs"><li class="tab active"><a href="#tabname1-1">sem_write.c</a></li><li class="tab"><a href="#tabname1-2">sem_read.c</a></li><li class="tab"><a href="#tabname1-3">Makefile</a></li></ul><div class="tab-content"><div class="tab-pane active" id="tabname1-1"><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span>   <span class="comment">/* perror fgets shmat*/</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/shm.h&gt;</span> <span class="comment">/* shmget shmat*/</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span> <span class="comment">/* shmget ftok */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span>  <span class="comment">/* strcpy */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span>  <span class="comment">/* system */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;signal.h&gt;</span>  <span class="comment">/* sigaction sigemptyset */</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span>    <span class="comment">/* sem_open For O_* constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span> <span class="comment">/* sem_open For mode constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span><span class="comment">/* sem_open sem_post sem_unlink */</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">deleteSemfile</span><span class="params">(<span class="type">int</span> sig)</span>;</span><br><span class="line"><span class="comment">/* 主函数 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span> *argv[])</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">key_t</span> key;</span><br><span class="line">	<span class="type">int</span> shmid;    <span class="comment">/* 共享内存ID */</span></span><br><span class="line">	<span class="type">char</span> *shmAddr;<span class="comment">/* 共享内存首地址 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sigaction</span> <span class="title">act</span>;</span> <span class="comment">/* 处理信号行为的结构体变量 */</span></span><br><span class="line">	<span class="type">sem_t</span> *sem_r, *sem_w; <span class="comment">/* 定义两个信号量 */</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* 1. 生成key */</span></span><br><span class="line">	key = ftok(<span class="string">&quot;./key.txt&quot;</span>, <span class="number">100</span>); <span class="comment">/* 需要提前创建一个key.txt文件 */</span></span><br><span class="line">	<span class="keyword">if</span>(key &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;ftok&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;key=%x\n&quot;</span>, key);</span><br><span class="line">	<span class="comment">/* 2. 创建或者打开共享内存 */</span></span><br><span class="line">	shmid = shmget(key, <span class="number">512</span>, IPC_CREAT|<span class="number">0666</span>);</span><br><span class="line">	<span class="keyword">if</span>(shmid &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;shmget&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;shmid=%d\n&quot;</span>, shmid);</span><br><span class="line">	<span class="comment">/* 3. 映射共享内存，即把指定的共享内存映射到进程的地址空间用于访问*/</span></span><br><span class="line">	shmAddr = shmat(shmid, <span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line">	<span class="keyword">if</span>(shmAddr &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;shmat&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;shmAddr=%p\n&quot;</span>, shmAddr);</span><br><span class="line">	<span class="comment">/* 4. 信号捕获 */</span></span><br><span class="line">	act.sa_handler = deleteSemfile;  <span class="comment">/* 指定信号处理函数 */</span></span><br><span class="line">	act.sa_flags = <span class="number">0</span>;                <span class="comment">/* sa_flags指定了一组标志，这些标志用于控制信号的处理过程 */</span></span><br><span class="line">	sigemptyset(&amp;act.sa_mask);       <span class="comment">/* 将信号集初始化为空 */</span></span><br><span class="line">	sigaction(SIGINT, &amp;act, <span class="literal">NULL</span>);   <span class="comment">/* 捕捉信号 Ctrl+c 发出*/</span></span><br><span class="line">	<span class="comment">/* 5. 信号量初始化(会在/dev/shm下创建相应的两个文件) */</span></span><br><span class="line">	sem_r = sem_open(<span class="string">&quot;mysem_r&quot;</span>, O_CREAT|O_RDWR, <span class="number">0666</span>, <span class="number">0</span>);</span><br><span class="line">	sem_w = sem_open(<span class="string">&quot;mysem_w&quot;</span>, O_CREAT|O_RDWR, <span class="number">0666</span>, <span class="number">1</span>);</span><br><span class="line">	<span class="comment">/* 注意：程序执行完毕后，上边两个文件被创建，重新执行两个进程程序的时候信号量已经存在，此时无法正常通信，需要删除两个文件 */</span></span><br><span class="line">	<span class="comment">/* 6. 写入数据 */</span></span><br><span class="line">	<span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		sem_wait(sem_w);<span class="comment">/* 获取资源 */</span></span><br><span class="line">		<span class="built_in">printf</span>(<span class="string">&quot;Please enter data:&quot;</span>);</span><br><span class="line">		fgets(shmAddr, <span class="number">500</span>, <span class="built_in">stdin</span>);</span><br><span class="line">		sem_post(sem_r);<span class="comment">/* 释放资源 */</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 删除 /dev/shm/mysem_w 文件*/</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">deleteSemfile</span><span class="params">(<span class="type">int</span> sig)</span></span><br><span class="line">&#123;</span><br><span class="line">	sem_unlink(<span class="string">&quot;mysem_w&quot;</span>);</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;Delete mysem_w!\n&quot;</span>);</span><br><span class="line">	<span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-pane" id="tabname1-2"><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span>   <span class="comment">/* perror fgets shmat*/</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/shm.h&gt;</span> <span class="comment">/* shmget shmat*/</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span> <span class="comment">/* shmget ftok */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span>  <span class="comment">/* strcpy */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span>  <span class="comment">/* system */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;signal.h&gt;</span>  <span class="comment">/* sigaction sigemptyset */</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span>    <span class="comment">/* sem_open For O_* constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span> <span class="comment">/* sem_open For mode constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span><span class="comment">/* sem_open sem_post */</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">deleteSemfile</span><span class="params">(<span class="type">int</span> sig)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 主函数 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span> *argv[])</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">key_t</span> key;     <span class="comment">/* key */</span></span><br><span class="line">	<span class="type">int</span> shmid;     <span class="comment">/* 共享内存ID */</span></span><br><span class="line">	<span class="type">char</span> *shmAddr; <span class="comment">/* 共享内存首地址 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sigaction</span> <span class="title">act</span>;</span> <span class="comment">/* 处理信号行为的结构体变量 */</span></span><br><span class="line">	<span class="type">sem_t</span> *sem_r, *sem_w; <span class="comment">/* 定义两个信号量 */</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* 1. 生成key */</span></span><br><span class="line">	key = ftok(<span class="string">&quot;./key.txt&quot;</span>, <span class="number">100</span>);<span class="comment">/* 需要提前创建一个key.txt文件 */</span></span><br><span class="line">	<span class="keyword">if</span>(key &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;ftok&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;key=%x\n&quot;</span>, key);</span><br><span class="line">	<span class="comment">/* 2. 创建或者打开共享内存 */</span></span><br><span class="line">	shmid = shmget(key, <span class="number">512</span>, IPC_CREAT|<span class="number">0666</span>);</span><br><span class="line">	<span class="keyword">if</span>(shmid &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;shmget&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;shmid=%d\n&quot;</span>, shmid);</span><br><span class="line">	<span class="comment">/* 3. 映射共享内存，即把指定的共享内存映射到进程的地址空间用于访问*/</span></span><br><span class="line">	shmAddr = shmat(shmid, <span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line">	<span class="keyword">if</span>(shmAddr &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;shmat&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;shmAddr=%p\n&quot;</span>, shmAddr);</span><br><span class="line">	<span class="comment">/* 4. 信号捕获 */</span></span><br><span class="line">	act.sa_handler = deleteSemfile;  <span class="comment">/* 指定信号处理函数 */</span></span><br><span class="line">	act.sa_flags = <span class="number">0</span>;                <span class="comment">/* sa_flags指定了一组标志，这些标志用于控制信号的处理过程 */</span></span><br><span class="line">	sigemptyset(&amp;act.sa_mask);       <span class="comment">/* 将信号集初始化为空 */</span></span><br><span class="line">	sigaction(SIGINT, &amp;act, <span class="literal">NULL</span>);   <span class="comment">/* 捕捉信号 Ctrl+c 发出*/</span></span><br><span class="line">	<span class="comment">/* 5. 信号量初始化(会在/dev/shm下创建相应的两个文件) */</span></span><br><span class="line">	sem_r = sem_open(<span class="string">&quot;mysem_r&quot;</span>, O_CREAT|O_RDWR, <span class="number">0666</span>, <span class="number">0</span>);</span><br><span class="line">	sem_w = sem_open(<span class="string">&quot;mysem_w&quot;</span>, O_CREAT|O_RDWR, <span class="number">0666</span>, <span class="number">1</span>);</span><br><span class="line">	<span class="comment">/* 注意：程序执行完毕后，上边两个文件被创建，重新执行两个进程程序的时候信号量已经存在，此时无法正常通信，需要删除两个文件 */</span></span><br><span class="line">	<span class="comment">/* 6. 写入数据 */</span></span><br><span class="line">	<span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		sem_wait(sem_r);<span class="comment">/* 获取资源 */</span></span><br><span class="line">		<span class="built_in">printf</span>(<span class="string">&quot;read data:%s\n&quot;</span>, shmAddr);</span><br><span class="line">		sem_post(sem_w);<span class="comment">/* 释放资源 */</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 删除 /dev/shm/mysem_r 文件*/</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">deleteSemfile</span><span class="params">(<span class="type">int</span> sig)</span></span><br><span class="line">&#123;</span><br><span class="line">	sem_unlink(<span class="string">&quot;mysem_r&quot;</span>);</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;Delete mysem_r!\n&quot;</span>);</span><br><span class="line">	<span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-pane" id="tabname1-3"><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">CC = gcc</span><br><span class="line"></span><br><span class="line">DEBUG = -g -O2 </span><br><span class="line">CFLAGS = -Wall</span><br><span class="line">LIB = -l pthread</span><br><span class="line"><span class="comment"># 所有.c文件去掉后缀</span></span><br><span class="line">OBJ_LIST = $&#123;patsubst %.c, %.o, $&#123;wildcard *.c&#125;&#125; </span><br><span class="line">TARGET_LIST = $&#123;patsubst %.c, %, $&#123;wildcard *.c&#125;&#125; </span><br><span class="line"></span><br><span class="line">all : <span class="variable">$(OBJ_LIST)</span></span><br><span class="line">	@for var in <span class="variable">$(TARGET_LIST)</span>; \</span><br><span class="line">	do \</span><br><span class="line">		<span class="variable">$(CC)</span> $$var.o -o $$var <span class="variable">$(LIB)</span>; \</span><br><span class="line">		echo <span class="variable">$(CC)</span> $$var.o -o $$var <span class="variable">$(LIB)</span>;\</span><br><span class="line">	done</span><br><span class="line"></span><br><span class="line"><span class="comment"># compile</span></span><br><span class="line">%.o : %.c</span><br><span class="line">	<span class="variable">$(CC)</span> <span class="variable">$(DEBUG)</span> -c <span class="variable">$(CFLAGS)</span> <span class="variable">$&lt;</span> -o <span class="variable">$@</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta"><span class="keyword">.PHONY</span>: all clean clean_o</span></span><br><span class="line">clean : clean_o</span><br><span class="line">	@rm -vf <span class="variable">$(TARGET_LIST)</span> </span><br><span class="line">	</span><br><span class="line">	</span><br><span class="line">clean_o :</span><br><span class="line">	@rm -vf *.o</span><br></pre></td></tr></table></figure></div></div></div><p>在终端执行以下命令编译程序，并分别在两个终端执行写入和读取的程序：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">make # 生成可执行文件</span><br><span class="line">./sem_write        # 共享内存写入</span><br><span class="line">./sem_read         # 共享内存读取</span><br></pre></td></tr></table></figure><p>然后，终端会有以下信息显示：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">执行 ./sem_write 的终端</span></span><br><span class="line">hk@vm:~/2Sharedfiles/5temp$ ./sem_write</span><br><span class="line">key=643d0b4e</span><br><span class="line">shmid=17</span><br><span class="line">shmAddr=0x7f3d7a36c000</span><br><span class="line">Please enter data:qwert</span><br><span class="line">Please enter data:^CDelete mysem_w!</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">执行 ./sem_read 的终端</span></span><br><span class="line">hk@vm:/mnt/hgfs/Sharedfiles/5temp$ ./sem_read</span><br><span class="line">key=643d0b4e</span><br><span class="line">shmid=17</span><br><span class="line">shmAddr=0x7f661a6ad000</span><br><span class="line">read data:qwert</span><br><span class="line"></span><br><span class="line">^CDelete mysem_r!</span><br></pre></td></tr></table></figure>
              </div>
            </details>

<h1 id="三、POSIX-无名信号量"><a href="#三、POSIX-无名信号量" class="headerlink" title="三、POSIX 无名信号量"></a><font size=3>三、POSIX 无名信号量</font></h1><p>有名信号量和无名信号量的差异在于创建和销毁的形式上，其他的是一样的。无名信号量只能存在于内存中，所以就要求使用信号量的进程必须能访问信号量所在的这一块内存，所以<strong>无名信号量只能应用在同一进程内的线程之间</strong>（共享进程的内存）。另外，该信号量的使用需要借助于共享内存，打开或者创建之前需要进行以下步骤：</p>
<ul>
<li>（1）申请<code>key</code>；</li>
<li>（2）创建共享内存区域；</li>
<li>（3）映射内存区域到进程的虚拟地址空间。</li>
</ul>
<h2 id="1-初始化无名信号量"><a href="#1-初始化无名信号量" class="headerlink" title="1. 初始化无名信号量"></a><font size=3>1. 初始化无名信号量</font></h2><h3 id="1-1-sem-init"><a href="#1-1-sem-init" class="headerlink" title="1.1 sem_init() "></a><font size=3>1.1 sem_init() </font></h3><h4 id="1-1-1-函数说明-1"><a href="#1-1-1-函数说明-1" class="headerlink" title="1.1.1 函数说明"></a><font size=3>1.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_init</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_init</span><span class="params">(<span class="type">sem_t</span> *sem, <span class="type">int</span> pshared, <span class="type">unsigned</span> <span class="type">int</span> value)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于初始化一个无名信号量。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><p><code>sem</code>：<code>sem_t</code>类型，需要初始化的无名信号量名称。</p>
</li>
<li><p><code>pshared</code>：<code>int</code>类型，表示这个信号量是在进程的线程之间共享，还是在进程之间共享。一般指定为<code>0</code>，表示这个无名信号量只能由初始化这个信号量的进程使用，不能在进程间使用，并且<code>Linux</code> 不支持使用无名信号量实现进程间的同步。</p>
</li>
<li><p><code>value</code>：<code>unsigned int</code> 类型，表示无名信号量的初始值。该初始不能超过<code>SEM_VALUE_MAX</code>，这个常值必须低于为<code>32767</code>。</p>
</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>表示错误。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span>           <span class="comment">/* For O_* constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span>        <span class="comment">/* For mode constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> sem_r; <span class="comment">/* 定义成全局变量 */</span></span><br><span class="line">sem_init(&amp;sem_r, <span class="number">0</span>, <span class="number">0</span>);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="1-1-2-使用实例-1"><a href="#1-1-2-使用实例-1" class="headerlink" title="1.1.2 使用实例"></a><font size=3>1.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="2-销毁无名信号量"><a href="#2-销毁无名信号量" class="headerlink" title="2. 销毁无名信号量"></a><font size=3>2. 销毁无名信号量</font></h2><h3 id="2-1-sem-destroy"><a href="#2-1-sem-destroy" class="headerlink" title="2.1 sem_destroy() "></a><font size=3>2.1 sem_destroy() </font></h3><h4 id="2-1-1-函数说明-1"><a href="#2-1-1-函数说明-1" class="headerlink" title="2.1.1 函数说明"></a><font size=3>2.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_destroy</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_destroy</span><span class="params">(<span class="type">sem_t</span> *sem)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于销毁一个无名信号量。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，需要关闭的信号量的地址。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;<span class="comment">/* 定义成全局变量 */</span></span><br><span class="line">sem_destroy(sem_r);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="2-1-2-使用实例-1"><a href="#2-1-2-使用实例-1" class="headerlink" title="2.1.2 使用实例"></a><font size=3>2.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="3-无名信号量的P操作"><a href="#3-无名信号量的P操作" class="headerlink" title="3. 无名信号量的P操作"></a><font size=3>3. 无名信号量的<code>P</code>操作</font></h2><p>与有名信号量的<code>P</code>操作一样。</p>
<h3 id="3-1-sem-wait"><a href="#3-1-sem-wait" class="headerlink" title="3.1 sem_wait()"></a><font size=3>3.1 sem_wait()</font></h3><h4 id="3-1-1-函数说明-1"><a href="#3-1-1-函数说明-1" class="headerlink" title="3.1.1 函数说明"></a><font size=3>3.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_wait</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_wait</span><span class="params">(<span class="type">sem_t</span> *sem)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于执行信号量的<code>P</code>操作，也就是获取资源。如果信号量的值大于<code>0</code>，则信号量继续递减，函数立即返回；如果信号量当前的值是<code>0</code>，那么调用就会阻塞，直到可以执行递减操作(即信号量的值升到<code>0</code>以上)，或者信号处理程序中断调用。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，表示需要等待的信号量。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line">sem_wait(sem_r);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="3-1-2-使用实例-1"><a href="#3-1-2-使用实例-1" class="headerlink" title="3.1.2 使用实例"></a><font size=3>3.1.2 使用实例</font></h4><p>暂无。</p>
<h3 id="3-2-sem-trywait"><a href="#3-2-sem-trywait" class="headerlink" title="3.2 sem_trywait() "></a><font size=3>3.2 sem_trywait() </font></h3><h4 id="3-2-1-函数说明"><a href="#3-2-1-函数说明" class="headerlink" title="3.2.1 函数说明"></a><font size=3>3.2.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_trywait</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_trywait</span><span class="params">(<span class="type">sem_t</span> *sem)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于执行信号量的<code>P</code>操作。<code>sem_trywait()</code>与<code>sem_wait()</code>相同，不同之处是如果不能立即执行递减操作而需要等待的话，调用此函数将返回错误(<code>errno</code>设置为<code>EAGAIN</code>)而不是阻塞。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，表示需要等待的信号量。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line">sem_trywait(sem_r);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="3-2-2-使用实例"><a href="#3-2-2-使用实例" class="headerlink" title="3.2.2 使用实例"></a><font size=3>3.2.2 使用实例</font></h4><p>暂无。</p>
<h3 id="3-3-sem-trywait"><a href="#3-3-sem-trywait" class="headerlink" title="3.3 sem_trywait() "></a><font size=3>3.3 sem_trywait() </font></h3><h4 id="3-3-1-函数说明"><a href="#3-3-1-函数说明" class="headerlink" title="3.3.1 函数说明"></a><font size=3>3.3.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_trywait</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_timedwait</span><span class="params">(<span class="type">sem_t</span> *sem, <span class="type">const</span> <span class="keyword">struct</span> timespec *abs_timeout)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于执行信号量的<code>P</code>操作。<code>sem_timedwait()</code>与<code>sem_wait()</code>相同，不同的是<code>abs_timeout</code>指定了如果不能立即执行递减操作而需要等待的时间，超时将会返回。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，表示需要等待的信号量。</li>
<li><code>abs_timeout</code>：<code>struct timespec</code>类型的结构体指针变量，它指向一个时间结构体，该时间结构体指定了自<code>Epoch (1970-01-01 00:00:00 +0000 (UTC))</code>以来的以秒和纳秒为单位的绝对超时。</li>
</ul>
<details class="folding-tag" blue><summary> 点击查看 struct timespec 结构体成员 </summary>
              <div class='content'>
              <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">timespec</span> </span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">	<span class="type">time_t</span> tv_sec;      <span class="comment">/* Seconds */</span></span><br><span class="line">	<span class="type">long</span>   tv_nsec;     <span class="comment">/* Nanoseconds [0 .. 999999999] */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
              </div>
            </details>

<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">timespec</span> <span class="title">tout</span>;</span></span><br><span class="line">sem_timedwait(sem_r, &amp;tout);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong>如果可以立即执行操作，那么<code>sem_timedwait()</code>永远不会出现超时错误，而不管<code>abs_timeout</code>的值是多少。</p>
<h4 id="3-3-2-使用实例"><a href="#3-3-2-使用实例" class="headerlink" title="3.3.2 使用实例"></a><font size=3>3.3.2 使用实例</font></h4><p>暂无。</p>
<h2 id="4-无名信号量的V操作"><a href="#4-无名信号量的V操作" class="headerlink" title="4. 无名信号量的V操作"></a><font size=3>4. 无名信号量的<code>V</code>操作</font></h2><p>与有名信号量的<code>V</code>操作一样。</p>
<h3 id="4-1-sem-post"><a href="#4-1-sem-post" class="headerlink" title="4.1 sem_post() "></a><font size=3>4.1 sem_post() </font></h3><h4 id="4-1-1-函数说明-1"><a href="#4-1-1-函数说明-1" class="headerlink" title="4.1.1 函数说明"></a><font size=3>4.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 3 sem_post</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link with -pthread. */</span></span><br><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">sem_post</span><span class="params">(<span class="type">sem_t</span> *sem)</span>;</span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于执行信号量的<code>V</code>操作，也就是获取资源。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>sem</code>：<code>sem_t *</code>类型，表示需释放的信号量。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">sem_t</span> *sem_r;</span><br><span class="line">sem_post(sem_r);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="4-1-2-使用实例-1"><a href="#4-1-2-使用实例-1" class="headerlink" title="4.1.2 使用实例"></a><font size=3>4.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="5-使用实例"><a href="#5-使用实例" class="headerlink" title="5. 使用实例"></a><font size=3>5. 使用实例</font></h2><details class="folding-tag" blue><summary> 点击查看实例 </summary>
              <div class='content'>
              <figure class="highlight c"><figcaption><span>test.c</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span>   <span class="comment">/* perror fgets shmat*/</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/shm.h&gt;</span> <span class="comment">/* shmget shmat*/</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span> <span class="comment">/* shmget ftok */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span>  <span class="comment">/* strcpy */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span>  <span class="comment">/* system */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;signal.h&gt;</span>  <span class="comment">/* sigaction sigemptyset */</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span>    <span class="comment">/* sem_init For O_* constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span> <span class="comment">/* sem_init For mode constants */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span><span class="comment">/* sem_init sem_post */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;pthread.h&gt;</span>    <span class="comment">/* pthread_create */</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="type">sem_t</span> sem_r, sem_w; <span class="comment">/* 定义两个信号量 */</span></span><br><span class="line"><span class="type">char</span> *shmAddr;      <span class="comment">/* 共享内存首地址 */</span></span><br><span class="line"></span><br><span class="line"><span class="type">void</span> *<span class="title function_">readSem</span><span class="params">(<span class="type">void</span> *arg)</span>;   <span class="comment">/* 读取数据线程 */</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">deleteSemfile</span><span class="params">(<span class="type">int</span> sig)</span>;<span class="comment">/* 删除无名信号量 */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 主函数 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span> *argv[])</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">key_t</span> key;</span><br><span class="line">	<span class="type">int</span> shmid;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sigaction</span> <span class="title">act</span>;</span><span class="comment">/* 处理信号行为的结构体变量 */</span></span><br><span class="line">	<span class="type">pthread_t</span> tid;</span><br><span class="line">	<span class="comment">/* 1. 生成key */</span></span><br><span class="line">	key = ftok(<span class="string">&quot;./key.txt&quot;</span>, <span class="number">100</span>);</span><br><span class="line">	<span class="keyword">if</span>(key &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;ftok&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;key=%x\n&quot;</span>, key);</span><br><span class="line">	<span class="comment">/* 2. 创建或者打开共享内存 */</span></span><br><span class="line">	shmid = shmget(key, <span class="number">512</span>, IPC_CREAT|<span class="number">0666</span>);</span><br><span class="line">	<span class="keyword">if</span>(shmid &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;shmget&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;shmid=%d\n&quot;</span>, shmid);</span><br><span class="line">	<span class="comment">/* 3. 映射共享内存，即把指定的共享内存映射到进程的地址空间用于访问*/</span></span><br><span class="line">	shmAddr = shmat(shmid, <span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line">	<span class="keyword">if</span>(shmAddr &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;shmat&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;shmAddr=%p\n&quot;</span>, shmAddr);</span><br><span class="line">	<span class="comment">/* 4. 信号捕获 */</span></span><br><span class="line">	act.sa_handler = deleteSemfile;  <span class="comment">/* 指定信号处理函数 */</span></span><br><span class="line">	act.sa_flags = <span class="number">0</span>;                <span class="comment">/* sa_flags指定了一组标志，这些标志用于控制信号的处理过程 */</span></span><br><span class="line">	sigemptyset(&amp;act.sa_mask);       <span class="comment">/* 将信号集初始化为空 */</span></span><br><span class="line">	sigaction(SIGINT, &amp;act, <span class="literal">NULL</span>);   <span class="comment">/* 捕捉信号 */</span></span><br><span class="line">	<span class="comment">/* 5. 信号量初始化) */</span></span><br><span class="line">	sem_init(&amp;sem_r, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">	sem_init(&amp;sem_w, <span class="number">0</span>, <span class="number">1</span>);</span><br><span class="line">	<span class="comment">/* 6. 创建线程 */</span></span><br><span class="line">	pthread_create(&amp;tid, <span class="literal">NULL</span>, readSem, <span class="literal">NULL</span>);</span><br><span class="line">	<span class="comment">/* 7. 写入数据 */</span></span><br><span class="line">	<span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		sem_wait(&amp;sem_w);<span class="comment">/* 获取资源 */</span></span><br><span class="line">		<span class="built_in">printf</span>(<span class="string">&quot;&gt;&quot;</span>);</span><br><span class="line">        fgets(shmAddr, <span class="number">500</span>, <span class="built_in">stdin</span>);</span><br><span class="line">		sem_post(&amp;sem_r);<span class="comment">/* 释放资源 */</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 线程函数 */</span></span><br><span class="line"><span class="type">void</span> *<span class="title function_">readSem</span><span class="params">(<span class="type">void</span> *arg)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		sem_wait(&amp;sem_r);</span><br><span class="line">		<span class="built_in">printf</span>(<span class="string">&quot;%s\n&quot;</span>,shmAddr);</span><br><span class="line">		sem_post(&amp;sem_w);</span><br><span class="line"></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 删除信号量 */</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">deleteSemfile</span><span class="params">(<span class="type">int</span> sig)</span></span><br><span class="line">&#123;</span><br><span class="line">	sem_destroy(&amp;sem_r);</span><br><span class="line">	sem_destroy(&amp;sem_w);</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;Destroy sem_r and sem_w!\n&quot;</span>);</span><br><span class="line">	<span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在终端执行以下命令编译程序：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">gcc test.c -Wall -lpthread # 生成可执行文件 a.out </span><br><span class="line">./a.out # 执行可执行程序</span><br></pre></td></tr></table></figure><p>然后，终端会有以下信息显示：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">key=643d0b38</span><br><span class="line">shmid=18</span><br><span class="line">shmAddr=0x7f421bd53000</span><br><span class="line"><span class="meta prompt_">&gt;</span><span class="language-bash">qwert</span></span><br><span class="line">qwert</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">&gt;</span><span class="language-bash">^CDestroy sem_r and sem_w!</span></span><br></pre></td></tr></table></figure>
              </div>
            </details>

<h1 id="四、System-V-信号量"><a href="#四、System-V-信号量" class="headerlink" title="四、System V 信号量"></a><font size=3>四、System V 信号量</font></h1><h2 id="1-创建或打开信号量"><a href="#1-创建或打开信号量" class="headerlink" title="1. 创建或打开信号量"></a><font size=3>1. 创建或打开信号量</font></h2><h3 id="1-1-semget"><a href="#1-1-semget" class="headerlink" title="1.1 semget() "></a><font size=3>1.1 semget() </font></h3><h4 id="1-1-1-函数说明-2"><a href="#1-1-1-函数说明-2" class="headerlink" title="1.1.1 函数说明"></a><font size=3>1.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 2 semget</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/sem.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">semget</span><span class="params">(<span class="type">key_t</span> key, <span class="type">int</span> nsems, <span class="type">int</span> semflg)</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于创建或者打开一个<code>System V</code>信号量集，并获取信号量集的<code>ID</code>。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>key</code>：<code>key_t</code>类型，<code>ftok</code>产生的<code>key</code>值（和信号灯关联）或者<code>IPC_PRIVATE </code>（这样只能用于具有血缘关系的进程通信）。</li>
<li><code>nsems</code>：<code>int</code>类型，信号量集中信号量的个数，当没有创建信号量集时，参数<code>nems</code>可以为<code>0</code>(表示不关心)。否则，<code>nems</code>必须大于<code>0</code>且小于等于每个信号量集(<code>SEMMSL</code>)的最大信号量数。</li>
<li><code>semflg</code>：<code>int</code>类型，信号灯集的访问权限，我们一般设置为<code>为IPC_CREAT |0666</code>。</li>
</ul>
<details class="folding-tag" blue><summary> 点击查看 semflg 取值详情 </summary>
              <div class='content'>
              <p>如果<code>key</code>值为<code>IPC_PRIVATE</code>，或者没有现有的信号量集与<code>key</code>相关联，并且在<code>semflg</code>中指定了<code>IPC_CREAT</code>，则会创建一组新的<code>nems</code>信号量。</p><p>如果<code>semflg</code>同时指定了<code>IPC_CREAT</code>和<code>IPC_EXCL</code>，并且<code>key</code>的信号量集已经存在，那么<code>semget()</code>将失败，<code>errno</code>被设置为<code>EEXIST</code>。</p>
              </div>
            </details>

<p><strong>【返回值】</strong><code>int</code>类型，成功返回信号量集标识符(<code>ID</code>)，否则返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/sem.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="type">int</span> semid;</span><br><span class="line">semid = semget(key, <span class="number">2</span>, IPC_CREAT|<span class="number">0666</span>);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="1-1-2-使用实例-2"><a href="#1-1-2-使用实例-2" class="headerlink" title="1.1.2 使用实例"></a><font size=3>1.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="2-信号量P、V操作实现"><a href="#2-信号量P、V操作实现" class="headerlink" title="2. 信号量P、V操作实现"></a><font size=3>2. 信号量<code>P</code>、<code>V</code>操作实现</font></h2><p>在<code>System V</code>信号量的相关函数中，没有直接实现<code>P</code>、<code>V</code>操作的函数，只有一个<code>semop</code>函数，通过这个函数，。我们可以自己实现对信号量加<code>1</code>和减<code>1</code>操作。</p>
<h3 id="2-1-semop"><a href="#2-1-semop" class="headerlink" title="2.1 semop() "></a><font size=3>2.1 semop() </font></h3><h4 id="2-1-1-函数说明-2"><a href="#2-1-1-函数说明-2" class="headerlink" title="2.1.1 函数说明"></a><font size=3>2.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 2 semop</code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/sem.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">semop</span><span class="params">(<span class="type">int</span> semid, <span class="keyword">struct</span> sembuf *sops, <span class="type">size_t</span> nsops)</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数用于实现信号量的<code>P</code>、<code>V</code>操作。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>semid</code>：<code>int</code>类型，已创建的信号量集的<code>ID</code>。</li>
<li><code>sops</code>：<code>struct sembuf</code>类型的结构体指针变量，<code>sops</code>所指向的信号集中的每一个<code>nops</code>元素都是一个结构体，用于指定在单个信号量上执行的操作。</li>
</ul>
<details class="folding-tag" blue><summary> 点击查看 struct sembuf 成员 </summary>
              <div class='content'>
              <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">sembuf</span> </span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">	<span class="type">short</span> sem_num;  <span class="comment">/* 要操作的信号灯的编号 */</span></span><br><span class="line">	<span class="type">short</span> sem_op;   <span class="comment">/* 1,释放资源，V操作; -1,分配资源，P操作 */</span></span><br><span class="line">	<span class="type">short</span> sem_flg;  <span class="comment">/* 0(阻塞), IPC_NOWAIT, SEM_UNDO */</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>【注意事项】定义一个<code>struct sembuf</code>类型的结构体变量，只能对某一个信号灯的操作，如果需要同时对多个信号量操作，则需要定义<code>struct sembuf</code>结构体数组或者多个<code>struct sembuf</code>结构体变量。</p>
              </div>
            </details>

<ul>
<li><code>nsops</code>：<code>size_t</code>类型，表示要进行操作的信号量的个数。</li>
</ul>
<p><strong>【返回值】</strong><code>int</code>类型，成功返回<code>0</code>，失败返回<code>-1</code>，并设置<code>errno</code>。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/sem.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">sembuf</span> <span class="title">sbuf</span>;</span></span><br><span class="line">sbuf.sem_num =  <span class="number">0</span>;</span><br><span class="line">sbuf.sem_op = <span class="number">1</span>;</span><br><span class="line">sbuf.sem_flg = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">semop(semid, &amp;sbuf, <span class="number">1</span>);</span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="2-1-2-使用实例-2"><a href="#2-1-2-使用实例-2" class="headerlink" title="2.1.2 使用实例"></a><font size=3>2.1.2 使用实例</font></h4><p>暂无。</p>
<h3 id="2-2-Poperation"><a href="#2-2-Poperation" class="headerlink" title="2.2 Poperation() "></a><font size=3>2.2 Poperation() </font></h3><p>该函数为自定义的信号量的<code>P</code>操作，通过<code>semop</code>实现。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @Function: Poperation</span></span><br><span class="line"><span class="comment"> * @Description: System V 信号量P操作，也就是获取资源</span></span><br><span class="line"><span class="comment"> * @param semid    : 已经创建的信号量集ID</span></span><br><span class="line"><span class="comment"> * @param semindex : 信号量在信号量集中的编号(索引)</span></span><br><span class="line"><span class="comment"> * @return  : none</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">Poperation</span><span class="params">(<span class="type">int</span> semid, <span class="type">int</span> semindex)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sembuf</span> <span class="title">sbuf</span>;</span></span><br><span class="line">	sbuf.sem_num =  semindex;</span><br><span class="line">	sbuf.sem_op = <span class="number">-1</span>;</span><br><span class="line">	sbuf.sem_flg = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">	semop(semid, &amp;sbuf, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-3-Voperation"><a href="#2-3-Voperation" class="headerlink" title="2.3 Voperation() "></a><font size=3>2.3 Voperation() </font></h3><p>该函数为自定义的信号量的<code>V</code>操作，通过<code>semop</code>实现。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @Function: Voperation</span></span><br><span class="line"><span class="comment"> * @Description: System V 信号量V操作，也就是释放资源</span></span><br><span class="line"><span class="comment"> * @param semid    : 已经创建的信号量集ID</span></span><br><span class="line"><span class="comment"> * @param semindex : 信号量在信号量集中的编号(索引)</span></span><br><span class="line"><span class="comment"> * @return  : none</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">Voperation</span><span class="params">(<span class="type">int</span> semid,<span class="type">int</span> semindex)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sembuf</span> <span class="title">sbuf</span>;</span></span><br><span class="line">	sbuf.sem_num =  semindex;</span><br><span class="line">	sbuf.sem_op = <span class="number">1</span>;</span><br><span class="line">	sbuf.sem_flg = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">	semop(semid, &amp;sbuf, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3-信号量集控制"><a href="#3-信号量集控制" class="headerlink" title="3. 信号量集控制"></a><font size=3>3. 信号量集控制</font></h2><h3 id="3-1-semctl"><a href="#3-1-semctl" class="headerlink" title="3.1 semctl() "></a><font size=3>3.1 semctl() </font></h3><h4 id="3-1-1-函数说明-2"><a href="#3-1-1-函数说明-2" class="headerlink" title="3.1.1 函数说明"></a><font size=3>3.1.1 函数说明</font></h4><p>在<code>linux</code>下可以使用<code>man 2 semctl </code>命令查看该函数的帮助手册。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/sem.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">semctl</span><span class="params">(<span class="type">int</span> semid, <span class="type">int</span> semnum, <span class="type">int</span> cmd, ...)</span>;<span class="comment">/* man手册函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">semctl</span><span class="params">(<span class="type">int</span> semid, <span class="type">int</span> semnum, <span class="type">int</span> cmd, ... <span class="comment">/* union semun arg */</span> )</span>;<span class="comment">/* 我自己加的 */</span></span><br></pre></td></tr></table></figure>

<p><strong>【函数说明】</strong>该函数对<code>semid</code>标识的<code>System V</code>信号量集或该信号量集的<code>semnum</code>信号量执行<code>cmd</code>指定的控制操作。(集合中的信号量从<code>0</code>开始编号)。</p>
<p><strong>【函数参数】</strong></p>
<ul>
<li><code>semid</code>：<code>int</code>类型，已创建的信号量集的<code>ID</code>。</li>
<li><code>semnum</code>：<code>int</code>类型，要操作的信号量集中的信号量编号。</li>
<li><code>cmd</code>：<code>int</code>类型，表示要执行的操作。</li>
</ul>
<details class="folding-tag" blue><summary> 点击查看 cmd 常见取值及含义 </summary>
              <div class='content'>
              <table>    <tr><td align="center" width=150px>GETVAL</td><td align="left">获取信号量的值，返回值是获得值。</td></tr>    <tr><td align="center" width=150px>SETVAL</td><td align="left">设置信号量的值，需要用到第四个参数，这个参数是一个共用体，后边会有介绍。</td></tr>    <tr><td align="center" width=150px>IPC_RMID</td><td align="left">从系统中删除信号量集合，唤醒所有因调用semop()阻塞在该信号量集合里的所有进程(相应调用会返回错误且errno被设置为EIDRM)。</td></tr></table>
              </div>
            </details>

<ul>
<li><code>arg</code>：<code>union semun</code>类型，当<code>cmd</code>为<code>SETVAL</code>时才会有该参数，该参数用于设置信号集中信号量的参数，一般使用<code>val</code>成员较多，该成员表示信号量的值。</li>
</ul>
<details class="folding-tag" blue><summary> 点击查看 union semun 成员 </summary>
              <div class='content'>
              <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">union</span> <span class="title">semun</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">	<span class="type">int</span>              val;    <span class="comment">/* Value for SETVAL */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">semid_ds</span> *<span class="title">buf</span>;</span>    <span class="comment">/* Buffer for IPC_STAT, IPC_SET */</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">short</span>  *<span class="built_in">array</span>;  <span class="comment">/* Array for GETALL, SETALL */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">seminfo</span>  *__<span class="title">buf</span>;</span>  <span class="comment">/* Buffer for IPC_INFO (Linux-specific) */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
              </div>
            </details>

<p><strong>【返回值】</strong><code>int</code>类型，成功时返回值受到<code>cmd</code>的影响，一般会返回<code>0</code>，失败都是返回<code>-1</code>，并设置<code>errno</code>，详情可查看<code>man</code>手册。</p>
<p><strong>【使用格式】</strong>一般情况下基本使用格式如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 需要包含的头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/sem.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 至少应该有的语句 */</span></span><br><span class="line"><span class="class"><span class="keyword">union</span> <span class="title">semun</span> <span class="title">mysem</span>;</span><span class="comment">/* 信号量参数结构体 */</span></span><br><span class="line">mysem.val = <span class="number">0</span>;    <span class="comment">/* 设置信号量的值 */</span></span><br><span class="line">semctl(semid, SEM_READ, SETVAL, mysem); <span class="comment">/* 初始化信号量 */</span></span><br></pre></td></tr></table></figure>

<p><strong>【注意事项】</strong><code>none</code></p>
<h4 id="3-1-2-使用实例-2"><a href="#3-1-2-使用实例-2" class="headerlink" title="3.1.2 使用实例"></a><font size=3>3.1.2 使用实例</font></h4><p>暂无。</p>
<h2 id="4-使用实例"><a href="#4-使用实例" class="headerlink" title="4. 使用实例"></a><font size=3>4. 使用实例</font></h2><p>需要提前说明的是，下边的例子只是为了测试<code>System V</code>信号量，最后没有释放共享内存区域。</p>
<details class="folding-tag" blue><summary> 点击查看实例 </summary>
              <div class='content'>
              <figure class="highlight c"><figcaption><span>test.c</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 头文件 */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span>   <span class="comment">/* perror fgets */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/shm.h&gt;</span> <span class="comment">/* shmget shmat */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/ipc.h&gt;</span> <span class="comment">/* semop semget ftok shmget shmat semctl */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/sem.h&gt;</span> <span class="comment">/* semop semget semctl */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span>  <span class="comment">/* system */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;signal.h&gt;</span>  <span class="comment">/* sigaction sigemptyset */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span><span class="comment">/* fork */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;unistd.h&gt;</span>   <span class="comment">/* fork */</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> SEM_READ   0  <span class="comment">/* 读信号量编号 */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> SEM_WRITE  1  <span class="comment">/* 写信号量编号 */</span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">union</span> <span class="title">semun</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">	<span class="type">int</span> val;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">Poperation</span><span class="params">(<span class="type">int</span> semid,<span class="type">int</span> semindex)</span>;<span class="comment">/* 获取资源 */</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">Voperation</span><span class="params">(<span class="type">int</span> semid,<span class="type">int</span> semindex)</span>;<span class="comment">/* 释放资源 */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 主函数 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span> *argv[])</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">key_t</span> key;</span><br><span class="line">	<span class="type">int</span> shmid, semid;</span><br><span class="line">	<span class="type">char</span> *shmAddr;</span><br><span class="line">	<span class="class"><span class="keyword">union</span> <span class="title">semun</span> <span class="title">mysem</span>;</span><span class="comment">/* 信号灯参数结构体 */</span></span><br><span class="line">	<span class="type">pid_t</span> pid;</span><br><span class="line">	<span class="comment">/* 1. 生成key */</span></span><br><span class="line">	key = ftok(<span class="string">&quot;./key.txt&quot;</span>, <span class="number">100</span>);</span><br><span class="line">	<span class="keyword">if</span>(key &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;ftok&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;key=%x\n&quot;</span>, key);</span><br><span class="line">	<span class="comment">/* 2. 创建或者打开共享内存 */</span></span><br><span class="line">	shmid = shmget(key, <span class="number">512</span>, IPC_CREAT|<span class="number">0666</span>);</span><br><span class="line">	<span class="keyword">if</span>(shmid &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;shmget&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;shmid=%d\n&quot;</span>, shmid);</span><br><span class="line">	<span class="comment">/* 3. 映射共享内存，即把指定的共享内存映射到进程的地址空间用于访问*/</span></span><br><span class="line">	shmAddr = shmat(shmid, <span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line">	<span class="keyword">if</span>(shmAddr &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;shmat&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;shmAddr=%p\n&quot;</span>, shmAddr);</span><br><span class="line">	<span class="comment">/* 4. 创建或者打开信号量集 */</span></span><br><span class="line">	semid = semget(key, <span class="number">2</span>, IPC_CREAT|<span class="number">0666</span>);<span class="comment">/* 信号量集包含两个信号量 */</span></span><br><span class="line">	<span class="keyword">if</span>(semid &lt; <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;semget&quot;</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="comment">/* 5. 初始化读写信号量 */</span></span><br><span class="line">	mysem.val = <span class="number">0</span>;</span><br><span class="line">	semctl(semid, SEM_READ, SETVAL, mysem);</span><br><span class="line">	mysem.val = <span class="number">1</span>;</span><br><span class="line">	semctl(semid, SEM_WRITE, SETVAL, mysem);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* 6. 创建父子进程 */</span></span><br><span class="line">	pid = fork();</span><br><span class="line">	<span class="keyword">if</span>(pid &lt; <span class="number">0</span>) <span class="comment">/* 创建出错 */</span></span><br><span class="line">	&#123;</span><br><span class="line">		perror(<span class="string">&quot;fork&quot;</span>);</span><br><span class="line"></span><br><span class="line">		shmctl(shmid, IPC_RMID, <span class="literal">NULL</span>);<span class="comment">/* 释放共享内存 */</span></span><br><span class="line">		semctl(semid, <span class="number">0</span>, IPC_RMID);   <span class="comment">/* 删除信号量 */</span></span><br><span class="line"></span><br><span class="line">		<span class="built_in">exit</span>(<span class="number">-1</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">else</span> <span class="keyword">if</span>(pid == <span class="number">0</span>) <span class="comment">/* 子进程 读信号量 */</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			Poperation(semid, SEM_READ);</span><br><span class="line">			<span class="built_in">printf</span>(<span class="string">&quot;%s\n&quot;</span>, shmAddr);</span><br><span class="line"></span><br><span class="line">			Voperation(semid, SEM_WRITE);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">else</span> <span class="comment">/* 父进程 写信号量*/</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			Poperation(semid, SEM_WRITE);</span><br><span class="line">			<span class="built_in">printf</span>(<span class="string">&quot;&gt;&quot;</span>);</span><br><span class="line">			fgets(shmAddr, <span class="number">32</span>, <span class="built_in">stdin</span>);</span><br><span class="line"></span><br><span class="line">			Voperation(semid, SEM_READ);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @Function: Poperation</span></span><br><span class="line"><span class="comment"> * @Description: System V 信号量P操作，也就是获取资源</span></span><br><span class="line"><span class="comment"> * @param semid    : 已经创建的信号量集ID</span></span><br><span class="line"><span class="comment"> * @param semindex : 信号量在信号量集中的编号(索引)</span></span><br><span class="line"><span class="comment"> * @return  : none</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">Poperation</span><span class="params">(<span class="type">int</span> semid,<span class="type">int</span> semindex)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sembuf</span> <span class="title">sbuf</span>;</span></span><br><span class="line">	sbuf.sem_num =  semindex;</span><br><span class="line">	sbuf.sem_op = <span class="number">-1</span>;</span><br><span class="line">	sbuf.sem_flg = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">	semop(semid, &amp;sbuf, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @Function: Poperation</span></span><br><span class="line"><span class="comment"> * @Description: System V 信号量V操作，也就是释放资源</span></span><br><span class="line"><span class="comment"> * @param semid    : 已经创建的信号量集ID</span></span><br><span class="line"><span class="comment"> * @param semindex : 信号量在信号量集中的编号(索引)</span></span><br><span class="line"><span class="comment"> * @return  : none</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">Voperation</span><span class="params">(<span class="type">int</span> semid,<span class="type">int</span> semindex)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sembuf</span> <span class="title">sbuf</span>;</span></span><br><span class="line">	sbuf.sem_num =  semindex;</span><br><span class="line">	sbuf.sem_op = <span class="number">1</span>;</span><br><span class="line">	sbuf.sem_flg = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">	semop(semid, &amp;sbuf, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在终端执行以下命令编译程序：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">gcc test.c -Wall # 生成可执行文件 a.out </span><br><span class="line">./a.out # 执行可执行程序</span><br></pre></td></tr></table></figure><p>然后，终端会有以下信息显示：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">key=643d0b38</span><br><span class="line">shmid=18</span><br><span class="line">shmAddr=0x7f92372a9000</span><br><span class="line"><span class="meta prompt_">&gt;</span><span class="language-bash">qidaink</span></span><br><span class="line">qidaink</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">&gt;</span><span class="language-bash"></span></span><br><span class="line"><span class="language-bash"></span></span><br></pre></td></tr></table></figure><p>当我们使用<code>Ctrl+c</code>结束进程后，使用<code>ipcs -m</code>显示所有的共享内存<code>IPC</code>对象信息，则有：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">------------ 共享内存段 --------------</span><br><span class="line">键        shmid      拥有者  权限     字节     连接数  状态      </span><br><span class="line">0x643d0b38 18         hk         666        512        0 </span><br></pre></td></tr></table></figure><p>可以发现确实没有释放，但是关注点是在信号量的操作，所以这里我们其实可以手动删除共享内存，就是使用<code>ipcrm -m shmid</code>命令</p>
              </div>
            </details>

    </div>

    
    
    

    <footer class="post-footer">




    <div>
        
            <div style="text-align:center;color: #ccc;font-size:14px;">
            ----------本文结束
            <i class="fas fa-fan fa-spin" style="color: #FF1493; font-size: 1rem"></i>
            感谢您的阅读----------
            </div>
        
    </div>





  
  <div class="my_post_copyright"> 
    <p><span>文章标题:</span><a href="/post/98ffd47a.html">LV05-05-进程通信-06-信号量</a></p>
    <p><span>文章作者:</span><a href="/" title="欢迎访问 《苏木》 的学习笔记">苏木</a></p>
    <p><span>发布时间:</span>2023年07月02日 - 21:52</p>
    <p><span>最后更新:</span>2025年06月14日 - 00:25</p>
    <p><span>原始链接:</span><a href="/post/98ffd47a.html" title="LV05-05-进程通信-06-信号量">https://sumumm.github.io/post/98ffd47a.html</a></p>
    <p><span>许可协议:</span><i class="fab fa-creative-commons"></i> <a rel="license" href= "https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p>  
  </div>
  


          <div class="post-tags">
              <a href="/tags/LV05-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" rel="tag"><i class="fa fa-tag"></i> LV05-操作系统</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/post/e644c6e.html" rel="prev" title="LV05-06-内存管理-01-什么是虚拟内存？">
                  <i class="fa fa-angle-left"></i> LV05-06-内存管理-01-什么是虚拟内存？
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/post/cea9db3c.html" rel="next" title="LV05-05-进程通信-05-消息队列">
                  LV05-05-进程通信-05-消息队列 <i class="fa fa-angle-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">

  <div class="copyright">
    &copy; 2017 – 
    <span itemprop="copyrightYear">2025</span>
    <span class="with-love">
      <i class="fa fa-heart"></i>
    </span>
    <span class="author" itemprop="copyrightHolder">苏木</span>
  </div>
<div class="wordcount">
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-line"></i>
    </span>
      <span>站点总字数：</span>
    <span title="站点总字数">3.7m</span>
  </span>
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span>站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">225:26</span>
  </span>
</div>




    <span id="sitetime"></span>
    <script defer language=javascript>
        function siteTime()
        {
            window.setTimeout("siteTime()", 1000);
            var seconds = 1000;
            var minutes = seconds * 60;
            var hours = minutes * 60;
            var days = hours * 24;
            var years = days * 365;
            var today = new Date();
            var todayYear = today.getFullYear();
            var todayMonth = today.getMonth()+1;
            var todayDate = today.getDate();
            var todayHour = today.getHours();
            var todayMinute = today.getMinutes();
            var todaySecond = today.getSeconds();
            /*==================================================
            Date.UTC() -- 返回date对象距世界标准时间(UTC)1970年1月1日午夜之间的毫秒数(时间戳)
            year        - 作为date对象的年份，为4位年份值
            month       - 0-11之间的整数，做为date对象的月份
            day         - 1-31之间的整数，做为date对象的天数
            hours       - 0(午夜24点)-23之间的整数，做为date对象的小时数
            minutes     - 0-59之间的整数，做为date对象的分钟数
            seconds     - 0-59之间的整数，做为date对象的秒数
            microseconds - 0-999之间的整数，做为date对象的毫秒数
            ==================================================*/
            var t1 = Date.UTC(2017, 
                              5, 
                              19, 
                              0, 
                              0, 
                              0); //北京时间
            var t2 = Date.UTC(todayYear,todayMonth,todayDate,todayHour,todayMinute,todaySecond);
            var diff = t2-t1;
            var diffYears = Math.floor(diff/years);
            var diffDays = Math.floor((diff/days)-diffYears*365);
            var diffHours = Math.floor((diff-(diffYears*365+diffDays)*days)/hours);
            var diffMinutes = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours)/minutes);
            var diffSeconds = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours-diffMinutes*minutes)/seconds);
            document.getElementById("sitetime").innerHTML="已在这里 "+diffYears+" 年 "+diffDays+" 天 "+diffHours+" 小时 "+diffMinutes+" 分钟 "+diffSeconds+" 秒";
        }
        siteTime();
    </script>



    </div>
  </footer>

  
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.6.0/pjax.min.js" integrity="sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.umd.js" integrity="sha256-ytMJGN3toR+a84u7g7NuHm91VIR06Q41kMWDr2pq7Zo=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js" integrity="sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>




  <script src="/js/third-party/fancybox.js"></script>

  <script src="/js/third-party/pace.js"></script>


  




  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.js","integrity":"sha256-MASABpB4tYktI2Oitl4t+78w/lyA+D7b/s9GEP0JOGI="}}</script>
<script src="/js/third-party/math/mathjax.js"></script>


 
        <div id="click-show-text"
            data-mobile = false
            data-text = 富强,民主,文明,和谐,自由,平等,公正,法制,爱国,敬业,诚信,友善
            data-fontsize = 15px
            data-random= false>
        </div>
       

      
        <script async src=https://cdn.jsdelivr.net/npm/hexo-next-mouse-effect@latest/click/showText.js></script>
      

      
    




    <script async src="/js/fancybox_param.js"></script>





<!-- APlayer本体 -->



</body>
</html>
